/*
 * Copyright (c) 2018, Nordic Semiconductor
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package no.nordicsemi.android.nrfmesh.node.adapter;

import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.graphics.Color;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.RecyclerView;
import no.nordicsemi.android.mesh.transport.Element;
import no.nordicsemi.android.mesh.transport.ProvisionedMeshNode;
import no.nordicsemi.android.mesh.utils.CompanyIdentifiers;
import no.nordicsemi.android.mesh.utils.MeshAddress;
import no.nordicsemi.android.mesh.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmesh.R;
import no.nordicsemi.android.nrfmesh.databinding.NetworkItemBinding;
import no.nordicsemi.android.nrfmesh.widgets.RemovableViewHolder;
import androidx.core.content.ContextCompat;

public class NodeAdapter extends RecyclerView.Adapter<NodeAdapter.ViewHolder> {

    private final AsyncListDiffer<ProvisionedMeshNode> differ = new AsyncListDiffer<>(this, new NodeDiffCallback());
    private OnItemClickListener mOnItemClickListener;
    private OnDeleteClickListener mOnDeleteClickListener;

    private ProvisionedMeshNode mSelectedNode;
    private List<ProvisionedMeshNode> mSelectedNodes = new ArrayList<>();
    private Set<ProvisionedMeshNode> mBlockedNodes = new HashSet<>();
    private Map<String, Integer> mAssignedColors = new HashMap<>();

    public NodeAdapter(@NonNull final LifecycleOwner owner,
                       @NonNull final LiveData<List<ProvisionedMeshNode>> provisionedNodesLiveData) {
        provisionedNodesLiveData.observe(owner, nodes -> {
            if (nodes != null) {
                differ.submitList(new ArrayList<>(nodes));
            }
        });
    }

    public void setOnItemClickListener(@NonNull final OnItemClickListener listener) {
        mOnItemClickListener = listener;
    }

    public void setOnDeleteClickListener(@NonNull final OnDeleteClickListener listener) {
        mOnDeleteClickListener = listener;
    }



    /**
     * 设置选中的节点（仅UI状态，不处理业务逻辑）
     */
    public void setSelectedNode(final ProvisionedMeshNode node) {
        int oldSelected = -1;
        int newSelected = -1;
        if (mSelectedNode != null) {
            oldSelected = getPositionByAddress(mSelectedNode.getUnicastAddress());
        }

        // 更新选中状态
        mSelectedNode = node;
        if (node != null) {
            newSelected = getPositionByAddress(node.getUnicastAddress());
        }

        // 只刷新变更的item
        if (oldSelected != -1) notifyItemChanged(oldSelected);
        if (newSelected != -1 && newSelected != oldSelected) notifyItemChanged(newSelected);
    }

    /**
     * 获取当前选中的节点
     */
    public ProvisionedMeshNode getSelectedNode() {
        return mSelectedNode;
    }

    /**
     * 设置多选节点列表
     */
    public void setSelectedNodes(final List<ProvisionedMeshNode> nodes) {
        mSelectedNodes.clear();
        if (nodes != null) {
            mSelectedNodes.addAll(nodes);
        }
        notifyDataSetChanged();
    }

    /**
     * 获取多选节点列表
     */
    public List<ProvisionedMeshNode> getSelectedNodes() {
        return new ArrayList<>(mSelectedNodes);
    }

    /**
     * 设置阻塞节点集合
     */
    public void setBlockedNodes(final Set<ProvisionedMeshNode> nodes) {
        mBlockedNodes.clear();
        if (nodes != null) {
            mBlockedNodes.addAll(nodes);
        }
        notifyDataSetChanged();
    }

    /**
     * 获取阻塞节点集合
     */
    public Set<ProvisionedMeshNode> getBlockedNodes() {
        return new HashSet<>(mBlockedNodes);
    }

    public void moveSelectedNodeToTop() {
        if (mSelectedNode == null) return;

        List<ProvisionedMeshNode> currentList = new ArrayList<>(differ.getCurrentList());

        int position = getPositionByAddress(mSelectedNode.getUnicastAddress());
        if (position > 0) {  // 如果已经在顶部了，就不用动了
            ProvisionedMeshNode node = currentList.remove(position);
            currentList.add(0, node);  // 添加到第一个位置
            differ.submitList(currentList);  // 更新数据列表
            notifyItemMoved(position, 0);    // 通知RecyclerView有移动
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {//创建一个新的ViewHolder实例，这个实例会持有与 network_item.xml 布局文件中控件绑定的视图
        return new NodeAdapter.ViewHolder(NetworkItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {//每个数据项绑定到相应的视图组件
        final ProvisionedMeshNode node = differ.getCurrentList().get(position);
        if (node != null) {
            holder.name.setText(node.getNodeName());
            holder.unicastAddress.setText(MeshParserUtils.bytesToHex(MeshAddress.addressIntToBytes(node.getUnicastAddress()), false));

            // 元素与厂商信息
            final Map<Integer, Element> elements = node.getElements();
            if (elements != null && !elements.isEmpty()) {
                holder.nodeInfoContainer.setVisibility(View.VISIBLE);
                if (node.getCompanyIdentifier() != null) {
                    holder.companyIdentifier.setText(CompanyIdentifiers.getCompanyName(node.getCompanyIdentifier().shortValue()));
                } else {
                    holder.companyIdentifier.setText(R.string.unknown);
                }
                holder.elements.setText(String.valueOf(elements.size()));
                holder.models.setText(String.valueOf(getModels(elements)));
            } else {
                holder.companyIdentifier.setText(R.string.unknown);
                holder.elements.setText(String.valueOf(node.getNumberOfElements()));
                holder.models.setText(R.string.unknown);
            }

            // 选中/阻塞状态渲染
            final boolean isSelected = mSelectedNodes.contains(node);
            final boolean isBlocked = mBlockedNodes.contains(node);
            if (isSelected) {
                holder.container.setBackgroundColor(ContextCompat.getColor(holder.container.getContext(), android.R.color.darker_gray));
                holder.itemView.setElevation(5f);
                holder.itemView.setScaleX(0.95f);
                holder.itemView.setScaleY(0.95f);
                holder.container.setPadding(0, 0, 0, 0);
            } else {
                holder.container.setBackgroundColor(ContextCompat.getColor(holder.container.getContext(), android.R.color.transparent));
                holder.name.setTextColor(ContextCompat.getColor(holder.container.getContext(), R.color.textColorPrimary));
                holder.unicastAddress.setTextColor(ContextCompat.getColor(holder.container.getContext(), R.color.textColorSecondary));
                holder.companyIdentifier.setTextColor(ContextCompat.getColor(holder.container.getContext(), R.color.textColorSecondary));
                holder.elements.setTextColor(ContextCompat.getColor(holder.container.getContext(), R.color.textColorSecondary));
                holder.models.setTextColor(ContextCompat.getColor(holder.container.getContext(), R.color.textColorSecondary));
                holder.itemView.setAlpha(1.0f);
                holder.itemView.setElevation(0f);
                holder.container.setPadding(0, 0, 0, 0);
                holder.itemView.setScaleX(1.0f);
                holder.itemView.setScaleY(1.0f);
            }

            // 根据已分配颜色渲染节点名称文本颜色
            final Integer assigned = mAssignedColors.get(String.valueOf(node.getUnicastAddress()));
            if (assigned != null) {
                holder.name.setTextColor(colorIntFor(assigned));
            }

            // 绑定滑动视图的 Tag 以支持滑动删除回调
            holder.getSwipeableView().setTag(node);
        }
    }

    @Override
    public int getItemCount() {
        return differ.getCurrentList().size();
    }

    public ProvisionedMeshNode getItem(final int position) {
        if (getItemCount() > 0 && position > -1) {
            return differ.getCurrentList().get(position);
        }
        return null;
    }

    public boolean isEmpty() {
        return getItemCount() == 0;
    }

    public void setAssignedColors(final Map<String, Integer> colors) {
        mAssignedColors = (colors != null) ? colors : new HashMap<>();
        notifyDataSetChanged();
    }

    private int colorIntFor(int color) {
        switch (color) {
            case 1: return Color.parseColor("#FFC0CB"); // 粉色
            case 2: return Color.GREEN;   // 绿色
            case 3: return Color.YELLOW;  // 黄色
            case 4: return Color.MAGENTA; // 紫色
            case 5: return Color.CYAN;    // 青色
            case 6: return Color.rgb(255, 165, 0); // 橙色
            default: return Color.BLACK;
        }
    }

    private int getModels(final Map<Integer, Element> elements) {
        int models = 0;
        for (Element element : elements.values()) {
            models += element.getMeshModels().size();
        }
        return models;
    }

    /**
     * 根据节点地址获取在列表中的位置
     */
    private int getPositionByAddress(int address) {
        List<ProvisionedMeshNode> list = differ.getCurrentList();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getUnicastAddress() == address) {
                return i;
            }
        }
        return -1;
    }

    @FunctionalInterface
    public interface OnItemClickListener {
        void onConfigureClicked(final ProvisionedMeshNode node);
    }

    @FunctionalInterface
    public interface OnDeleteClickListener {
        void onDeleteClicked(final int position, final ProvisionedMeshNode node);
    }



    public final class ViewHolder extends RemovableViewHolder {
        FrameLayout container;
        TextView name;
        View nodeInfoContainer;
        TextView unicastAddress;
        TextView companyIdentifier;
        TextView elements;
        TextView models;


        @SuppressLint("NotifyDataSetChanged")
        private ViewHolder(final @NonNull NetworkItemBinding binding) {//绑定network_item.xml文件中的视图元素
            super(binding.getRoot());
            container = binding.container;
            name = binding.nodeName;
            nodeInfoContainer = binding.configuredNodeInfoContainer;
            unicastAddress = binding.unicast;
            companyIdentifier = binding.companyIdentifier;
            elements = binding.elements;
            models = binding.models;
            container.setOnClickListener(v -> {
                if (mOnItemClickListener != null) {
                    ProvisionedMeshNode clickedNode = differ.getCurrentList().get(getAbsoluteAdapterPosition());
                    moveSelectedNodeToTop();       // 让节点置顶
                    mOnItemClickListener.onConfigureClicked(clickedNode);  // 回调
                }
            });

            // 删除图标点击触发删除确认
            final View deleteView = itemView.findViewById(R.id.icon_delete);
            if (deleteView != null) {
                deleteView.setOnClickListener(v -> {
                    if (mOnDeleteClickListener != null && getAbsoluteAdapterPosition() != RecyclerView.NO_POSITION) {
                        final ProvisionedMeshNode node = differ.getCurrentList().get(getAbsoluteAdapterPosition());
                        mOnDeleteClickListener.onDeleteClicked(getAbsoluteAdapterPosition(), node);
                    }
                });
            }


        }
    }
}
